#include "gamewidget.h"
#include <QMessageBox>
#include <QTime>

const QColor SNAKE_COLOR(255, 192, 203); // 粉色
const QList<QColor> FOOD_COLORS{Qt::yellow, Qt::blue, Qt::red};

GameWidget::GameWidget(QWidget *parent)
    : QWidget(parent), cellSize(20), speedUp(false) {
    setFixedSize(1094, 656);
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &GameWidget::gameUpdate);
    initGame();
    setFocusPolicy(Qt::StrongFocus);
}

void GameWidget::initGame() {
    snake = {{5,5}, {4,5}, {3,5}};
    dir = Right;
    qsrand(QTime::currentTime().msec());
    generateFood();
    timer->start(200);
}

void GameWidget::generateFood() {
    const int maxX = width()/cellSize - 1;
    const int maxY = height()/cellSize - 1;

    do {
        food.setX(qrand() % maxX);
        food.setY(qrand() % maxY);
    } while(snake.contains(food));

    foodColor = FOOD_COLORS[qrand() % 3];
}

void GameWidget::paintEvent(QPaintEvent *) {
    QPainter painter(this);

    // 绘制自适应背景
    if(!m_background.isNull()) {
        painter.drawPixmap(rect(), m_background.scaled(size(),
           Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
    }

    // 绘制网格
    painter.setPen(QColor(220, 220, 220));
    for(int x=0; x<width(); x+=cellSize)
        painter.drawLine(x, 0, x, height());
    for(int y=0; y<height(); y+=cellSize)
        painter.drawLine(0, y, width(), y);

    // 绘制蛇身
    painter.setBrush(SNAKE_COLOR);
    painter.setPen(Qt::NoPen);
    for(const auto &p : snake) {
        painter.drawRect(p.x()*cellSize +1,
                        p.y()*cellSize +1,
                        cellSize-2,
                        cellSize-2);
    }

    // 绘制食物
    painter.setBrush(foodColor);
    painter.drawEllipse(food.x()*cellSize +2,
                       food.y()*cellSize +2,
                       cellSize-4,
                       cellSize-4);
}

void GameWidget::keyPressEvent(QKeyEvent *event) {
    switch(event->key()) {
    case Qt::Key_W: if(dir != Down) dir = Up; break;
    case Qt::Key_S: if(dir != Up) dir = Down; break;
    case Qt::Key_A: if(dir != Right) dir = Left; break;
    case Qt::Key_D: if(dir != Left) dir = Right; break;
    case Qt::Key_Shift:
        timer->setInterval(speedUp ? 200 : 100);
        speedUp = !speedUp;
        break;
    }
}

void GameWidget::gameUpdate() {
    QPoint newHead = snake.first();

    switch(dir) {
    case Up: newHead.ry()--; break;
    case Down: newHead.ry()++; break;
    case Left: newHead.rx()--; break;
    case Right: newHead.rx()++; break;
    }

    if(newHead.x()<0 || newHead.x()>=width()/cellSize ||
       newHead.y()<0 || newHead.y()>=height()/cellSize ||
       snake.contains(newHead)) {
        gameOver();
        return;
    }

    snake.prepend(newHead);
    newHead == food ? generateFood() : snake.removeLast();
    update();
}

void GameWidget::gameOver() {
    timer->stop();
    QMessageBox::information(this, "游戏结束", "游戏结束！");
    initGame();
}
